﻿
// ## 2023/12/21 ##
namespace AI_UNIT_ORDER_PRESET
{
    pk::c_bool 调试模式 = pk::c_bool(false);
    pk::c_bool 调试模式2 = pk::c_bool(false);

    class Main
    {
        pk::c_bool 调试模式 = pk::c_bool(false);
        pk::c_bool 调试模式2 = pk::c_bool(false);


        Main()
        {

            pk::set_func(266, pk::func266_t(callback));
            pk::bind(260, pk::trigger260_t(部队任务_266_打印));
        }


        void 部队任务_266_打印()
        {
            ImGui::Checkbox("调试模式", 调试模式);
            ImGui::Checkbox("调试模式2", 调试模式2);
        }

        void callback(pk::ai_context@ ai_context, pk::unit@ unit)
        {
            UNIT_ORDER_PRESET(ai_context, unit);
        }

        pk::list<pk::unit @> list_candidate_unit;
        pk::list<pk::building @> list_candidate_building;
        pk::list<pk::unit @> list_ally_unit;
        pk::unit @src_unit;

        array<float> heishu_weight(6, 0.0f);
        array<unit_order_info> unit_order_info_arr;
        float heishu_null = 0.0f;
        float heishu_weak = 0.5f;
        float heishu_normal = 1.0f;
        float heishu_strong = 1.5f;

        //运行此函数后紧接着就会run_unit_order，所以实际上此函数就是给ai部队做一次命令修正，deploy_target存的是部队此次出征的最终目标或长期目标，而unit_oder和unit_target则是短期任务。
        //所以此函数就是每回合执行任务前，根据部队的长期目标来修正部队的短期任务
        void UNIT_ORDER_PRESET(pk::ai_context@ ai_context, pk::unit@ unit)
        {
             //初始赋值全放这儿
            //if (unit.get_id() == 52) pk::trace(pk::format("UNIT_ORDER_PRESET{},{}", pk::is_alive(pk::get_unit(32)), pk::decode(pk::get_name(pk::get_unit(32)))));

            int unit_id = unit.get_id();
            pk::force@ force = @ai_context.force;
            int src_force_id = force.get_id();
            if (!pk::is_valid_normal_force_id(src_force_id)) return;
            int unit_order = unit.order;
            pk::map_object@ target = pk::get_target_map_object(unit);//496220
            int service = pk::get_service(unit);

            uint8 unit_deploy_type = 0;
            uint8 deploy_target = 255;

            auto scenario_ai_table_unit = pk::get_scenario().ai_table.unit[unit_id];
            if (int(scenario_ai_table_unit.force) == src_force_id)
            {
                unit_deploy_type = scenario_ai_table_unit.deploy_type;// 种类(3:运输，4:建设)
                deploy_target = scenario_ai_table_unit.deploy_target;
            }
            pk::building@ deploy_target_building = pk::get_building(deploy_target);
            pk::person@ leader = pk::get_person(unit.leader);
            int unit_pos_base_id = pk::get_building_id(unit.get_pos());

            if (调试模式2.v)pk::trace(pk::format("func266:{}0短期任务检测,unit.order{},短期任务类型{}, ", pk::decode(pk::get_name(unit)), unit.order, unit.target_type));
            if (调试模式2.v)pk::trace(pk::format("func266:{}0长期任务检测,unit_deploy_type{},deploy_target{}, ", pk::decode(pk::get_name(unit)), unit_deploy_type, deploy_target));


           //玩家第一军团不做处理
            if (unit.is_player() and unit.get_district_id() == pk::get_district_id(force, 1))
                return;


            if (!pk::is_alive(unit))
                return;

            //排除府兵武将
            if (leader.get_id() == 1000)
                return;

            if (unit_order == 部队任务_撤退)
            {
                //正常撤退,不作处理
                if (pk::get_building(service).get_force_id() == src_force_id)
                    return;
                else
                {
                    //重新选择据点,就近撤退
                    pk::building @dst = find_withdraw_base(unit);
                    pk::set_order(unit, 部队任务_撤退, dst.pos);
                }
            }

            if (调试模式2.v)pk::trace(pk::format("func266:{}01任务检测,unit.order{}, ", pk::decode(pk::get_name(unit)), unit.order));

            if (pk::is_valid_force_id(unit.requested_from))
            {
                if (ai_context.is_food_shortage(unit_id) || unit.get_troops() <= 500 || pk::is_enemy(src_force_id, unit.requested_from) || !pk::is_alive(target))
                {
                    pk::set_default_ai_order(unit);
                }

                //LABEL_99:
                if (!pk::is_enemy(src_force_id, target.get_force_id()))
                    pk::set_default_ai_order(unit);
                return;
            }

            if (调试模式2.v) pk::trace(pk::format("func266:{}02任务检测,unit.order{}, ", pk::decode(pk::get_name(unit)), unit.order));

            if (!check_target_suitability(unit) or !unit.is_player())//玩家其他军团或者电脑势力
            {
                if (调试模式2.v) pk::trace(pk::format("func266:{}03任务检测,unit.order{}, ", pk::decode(pk::get_name(unit)), unit.order));


            // *****************************************************************************************************************
            // ************************************************主逻辑:部队任务优化(放在799)***********************************
            // *******************************************************************************************************************
                核心任务优化::optimize_order(ai_context, unit);

                // *****************************************************************************************************************
                // ************************************************主逻辑:根据长期任务修正短期任务***********************************
                // *******************************************************************************************************************

                          // *************************************************** 进攻模块********************************************
                if (unit_deploy_type == 部队出征类型_攻击)
                {
                   //这段是玩家军团方针对部队行动目标的修正
                    if (unit.is_player())
                    {
                        int district_id = unit.get_district_id();
                        auto district = pk::get_district(district_id);
                        int policy = district.policy;
                        //玩家军团方针是都市攻略时，只攻击对应城，玩家军团方针是势力攻略时，只攻击对应势力
                        if (policy != 军团方针_势力攻略)
                        {
                            if (policy == 军团方针_都市攻略)
                            {
                                uint policy_target = district.policy_target;
                                if (pk::is_valid_city_id(policy_target))
                                {
                                    //如果部队目标在方针目标的临近据点内，且势力和方针目标相同，不重设
                                    if (policy_target != deploy_target)//这里理论上应该要改成只要是目标城市路径上的建筑也可以攻击才好
                                    {
                                        pk::building@ policy_target_building = pk::get_building(policy_target);
                                        bool need_reset = true;
                                        if (deploy_target_building.get_force_id() == policy_target_building.get_force_id())
                                        {
                                            if (ai::base_near_baselist[policy_target].contains(deploy_target_building))
                                            {
                                                if (ai::base_near_baselist[service].contains(deploy_target_building))
                                                    need_reset = false;
                                            }
                                        }

                                        if (need_reset) pk::set_default_ai_order(unit);
                                        return;
                                    }
                                }
                            }
                        }
                        else                                  // else只有是势力攻略了
                        {
                            int policy_target = district.policy_target;//这时候目标是势力
                            if (pk::is_valid_force_id(policy_target) && pk::is_alive(deploy_target_building) && policy_target != deploy_target_building.get_force_id())
                            {
                                pk::set_default_ai_order(unit);
                                return;
                            }
                        }
                    }

                    if (调试模式2.v)pk::trace(pk::format("func266:{}04任务检测,unit_deploy_t123ype{}, ", pk::decode(pk::get_name(unit)), unit_deploy_type));

                     //出征部队的回援，适用ai和玩家军团
                    if (pk::is_player_controlled(unit) and pk::is_alive(pk::get_building(service)))
                    {
                        if (pk::get_building(service).get_force_id() == src_force_id)
                        {

                            if (unit.type != 部队类型_战斗)
                                return; // 如果不是战斗部队，则排除运输部队

                            if (ai::base_around_enemy_troops[leader.service] > 20000 and ai::base_around_enemy_troops[leader.service] > ai::base_around_self_troops[leader.service] * 2)
                            {
                                //pk::set_order(unit, 部队任务_撤退, pk::get_building(leader.service).pos);
                                scenario_ai_table_unit.force = src_force_id;
                                scenario_ai_table_unit.deploy_type = 2;
                                scenario_ai_table_unit.deploy_target = service;
                                pk::set_order(unit, 部队任务_拦截, pk::point(-1, -1), 0);

                                if (调试模式2.v)pk::info(pk::format("{} 向:{}回防", pk::decode(pk::get_name(pk::get_person(unit.leader))), pk::decode(pk::get_name(pk::get_building(leader.service)))));
                                return;
                            }
                        }
                    }

                    if (调试模式2.v)pk::trace(pk::format("func266:{}05任务检测,unit_deploy_type{}, ", pk::decode(pk::get_name(unit)), unit_deploy_type));

                          // pk::trace(pk::format("{}遍历:部队短期任务类型{},短期任务目标:{}", pk::decode(pk::get_name(unit)), unit.order,unit.target));


                          //长期任务正常 ,但是短期攻击任务异常,这时候修复到长期攻击任务
                          //如果未能修复,也不要return,可以用最后的repair.
                    if (check_unit_deploy_type(ai_context, src_force_id, 部队出征类型_攻击, deploy_target))
                    {
                        if (unit.type != 部队类型_运输 and unit_order != 部队任务_撤退)
                        {
                            if (abnormal_task(unit))
                            {
                                pk::set_order(unit, pk::rand_bool(50) ? 部队任务_攻击 : 部队任务_征服, deploy_target_building.get_pos(), 0);// 运输队攻击玩家城市的原因？
                            }

                        }
                    }
                    if (调试模式2.v)pk::trace(pk::format("func266:{}06任务检测,unit_deploy_t123ype{}, ", pk::decode(pk::get_name(unit)), unit_deploy_type));

                   //攻击的目标已经被攻下,选择进城(但是如果城市满了应该换个地方进城,后面写)
                    if (pk::is_alive(deploy_target_building) && deploy_target_building.get_force_id() == src_force_id)
                    {
                        if (调试模式2.v)pk::trace(pk::format("func266:{}07任务检测,unit_deploy_t123ype{}, ", pk::decode(pk::get_name(unit)), unit_deploy_type));

                        //如果部队的任务目标就是城市或者据点本身,且这个据点也被攻下,则可以进入这个base
                        if (unit.target_type == 部队任务对象_据点 and unit.order != 部队任务_设置 and unit.order != 部队任务_修复 and pk::get_building(unit.target) !is null and unit.target <据点_末 and unit.target>-1 and pk::get_building(unit.target).get_force_id() == unit.get_force_id())

                        {
                            pk::set_order(unit, 部队任务_移动, deploy_target_building.get_pos(), 0);
                            if (调试模式2.v)pk::trace(pk::format("func266:{}08任务检测,unit_deploy_t123ype{}, ", pk::decode(pk::get_name(unit)), unit_deploy_type));

                        }

                        //如果队伍目标不是据点,而是建筑(封地等),当这个封地也被攻下的时候,进入长期任务据点.
                        if (unit.target_type == 部队任务对象_据点 and unit.order != 部队任务_设置 and unit.order != 部队任务_修复 and pk::get_building(unit.target) !is null and unit.target >= 据点_末 and pk::get_building(unit.target).get_force_id() == unit.get_force_id())
                        {
                            if (调试模式2.v)pk::trace(pk::format("func266:{}09任务检测,unit_deploy_t123ype{}, ", pk::decode(pk::get_name(unit)), unit_deploy_type));
                            pk::set_order(unit, 部队任务_移动, deploy_target_building.get_pos(), 0);
                        }

                        //如果队伍目标是以坐标的方式攻下的县城,,当这个封地也被攻下的时候,进入长期任务据点.
                        if (unit.target_type == 部队任务对象_坐标 or unit.target_type == 部队任务对象_无)
                        {
                            if (调试模式2.v)pk::trace(pk::format("func266:{}10任务检测,unit_deploy_t123ype{}, ", pk::decode(pk::get_name(unit)), unit_deploy_type));
                            if (pk::is_valid_pos(unit.target_pos))
                            {
                                pk::building @building_x = pk::get_building(unit.target_pos);
                                if (building_x !is null and building_x.get_id() >= 据点_末 and building_x.get_force_id() == unit.get_force_id())
                                    pk::set_order(unit, 部队任务_移动, deploy_target_building.get_pos(), 0);
                                return;
                            }
                        }

                    }
                }


               // *************************************************** 防御模块********************************************
                //只要防御的据点还是自己的,就应该改任务,但是要考虑如果长期任务不对,怎么办,以及如果走出自己城市范围怎么办,要精细化处理
                //如果未能修复,也不要return,可以用最后的repair.
                else  if (unit_deploy_type == 部队出征类型_防御)
                {
                    if (check_unit_deploy_type(ai_context, src_force_id, 部队出征类型_防御, deploy_target) and pk::get_building(unit_pos_base_id).get_force_id() == src_force_id)
                    {
                        if (abnormal_task(unit))
                        {
                            pk::set_order(unit, 部队任务_拦截, pk::point(-1, -1), 0);
                        }
                    }
                }


            // *************************************************** 运输模块********************************************

            //运输部队遇事不决应该尽快撤退,也不需要repair这里使用return没问题,
                else if (unit_deploy_type == 部队出征类型_运输)
                {
                    if (!check_unit_deploy_type(ai_context, src_force_id, 部队出征类型_运输, deploy_target))
                    {
                        if (unit_order != 部队任务_撤退)
                            pk::set_default_ai_order(unit);
                        return;
                    }
                    if (unit_order == 部队任务_移动 && pk::is_valid_pos(unit.target_pos))
                        pk::set_order(unit, 部队任务_移动, deploy_target_building.get_pos(), 0);
                    auto target_obj = pk::get_target_map_object(unit);
                    if (pk::is_alive(target_obj) and target_obj.get_type_id() == pk::building::type_id and target_obj.get_force_id() != unit.get_force_id())
                        pk::set_default_ai_order(unit);

                       // pk::set_order(unit, 部队任务_移动, deploy_target_building.get_pos(), 0);
                    return;
                }


                // *************************************************** 建设模块********************************************

                //建设部队遇事不决应该尽快撤退,也不需要repair这里使用return没问题,
                else if (unit_deploy_type == 部队出征类型_建设)
                {
                    if (unit.gold >= 200 && check_unit_deploy_type(ai_context, src_force_id, 部队出征类型_建设, deploy_target))
                    {
                        if (unit_order != -1)
                        {
                            if (unit_order == 部队任务_待命)
                                pk::set_default_ai_order(unit);
                            return;
                        }
                    }
                    else if (unit_order == 部队任务_撤退)
                    {
                        return;
                    }
                }


                // *********************************************其他情况********************************************  
                //当长期任务类型为0的时候,如果短期任务正常就不管他,短期任务异常就重设.
                else if (abnormal_task(unit))
                {
                    if (repair_to_ally(unit)) return;
                    if (repair_to_unit(unit)) return;
                    if (repair_to_building(unit)) return;
                }

                if (调试模式2.v)pk::trace(pk::format("func266:{}09任务检测,结束阶段1,unit_deploy_type{}, ", pk::decode(pk::get_name(unit)), unit_deploy_type));

              // *************************************************** 最终修复战斗部队********************************************  

                              //经过以上情况之后,依然异常的部队
                if (abnormal_task(unit))
                {
                    bool cmd = false;
                    if (repair_to_ally(unit)) return;
                    if (repair_to_unit(unit)) return;
                    if (repair_to_building(unit)) return;
                    //实在不行,就近撤退
                    pk::building @dst = find_withdraw_base(unit);
                    if (pk::is_alive(dst))
                    {
                        pk::set_order(unit, 部队任务_撤退, dst.pos);
                        if (调试模式2.v) pk::trace(pk::format("func266:{}任务异常,修改为撤退任务, ", pk::decode(pk::get_name(unit))));

                    }

                }
            }


               //经过以上情况之后,依然异常的军团部队
            if (abnormal_task(unit) and unit.is_player() and pk::get_district(unit.get_district_id()).no > 1)
            {
                // bool cmd = false;
                // if (repair_to_ally(unit)) return;
                // if (repair_to_unit(unit)) return;
                // if (repair_to_building(unit)) return;
                //实在不行,就近撤退
                pk::building @dst = find_withdraw_base(unit);
                pk::set_order(unit, 部队任务_撤退, dst.pos);
                if (调试模式2.v) pk::trace(pk::format("func266:{}任务异常,修改为撤退任务, ", pk::decode(pk::get_name(unit))));
            }

            return;
        }

        bool abnormal_task(pk::unit @unit)

        {

            int service = pk::get_service(unit);

            int unit_deploy_type = 0;
            int deploy_target = 255;

            auto scenario_ai_table_unit = pk::get_scenario().ai_table.unit[unit.get_id()];

            unit_deploy_type = scenario_ai_table_unit.deploy_type;// 种类(3:运输，4:建设)
            deploy_target = scenario_ai_table_unit.deploy_target;

            pk::building@ deploy_target_building = pk::get_building(deploy_target);

            if (调试模式2.v) pk::trace(pk::format("func266:{}1abnormal_task,unit.order{}, ", pk::decode(pk::get_name(unit)), unit.order));
            if (unit.target == -1)
                return true;
            if (调试模式2.v)pk::trace(pk::format("func266:{}2abnormal_task,unit.order{}, ", pk::decode(pk::get_name(unit)), unit.order));
            if (unit.order == 部队任务_待命)
                return true;
            if (调试模式2.v)pk::trace(pk::format("func266:{}3abnormal_task,unit.order{}, ", pk::decode(pk::get_name(unit)), unit.order));

              //如果部队的任务目标就是空建筑
            if (unit.target_type == 部队任务对象_据点 and pk::get_building(unit.target) is null)
                return true;
            if (调试模式2.v)pk::trace(pk::format("func266:{}4abnormal_task,unit.order{}, ", pk::decode(pk::get_name(unit)), unit.order));

              //如果部队的任务目标就是空建筑
            if (unit.target_type == 部队任务对象_部队 and pk::get_unit(unit.target) is null)
                return true;
            if (调试模式2.v)pk::trace(pk::format("func266:{}5abnormal_task,unit.order{}, ", pk::decode(pk::get_name(unit)), unit.order));

              //如果部队的任务目标就是空建筑
            if (unit.target_type == 部队任务对象_坐标 and !pk::is_valid_pos(unit.target_pos))
                return true;
            if (调试模式2.v)pk::trace(pk::format("func266:{}6abnormal_task,unit.order{}, ", pk::decode(pk::get_name(unit)), unit.order));


            //如果部队的任务目标不是长期目标
            if (unit.target_type == 部队任务对象_据点 and unit.order == 部队任务_攻击 and pk::get_building(unit.target) !is null and unit.target < 据点_末 and pk::get_building(unit.target).get_force_id() != unit.get_force_id())
            {
                if (unit_deploy_type == 部队出征类型_攻击 and unit.target != deploy_target)
                    return true;
            }

        //如果部队的任务目标是己方封地
            if (unit.target_type == 部队任务对象_据点 and unit.order != 部队任务_设置 and unit.order != 部队任务_修复 and pk::get_building(unit.target) !is null and unit.target >= 据点_末 and pk::get_building(unit.target).get_force_id() == unit.get_force_id())
                return true;
            if (调试模式2.v)pk::trace(pk::format("func266:{}7abnormal_task,unit.order{}, ", pk::decode(pk::get_name(unit)), unit.order));
            //如果部队的任务目标是不可进攻封地
            if (unit.target_type == 部队任务对象_据点 and unit.order != 部队任务_设置 and unit.order != 部队任务_修复 and pk::get_building(unit.target) !is null and unit.target >= 据点_末 and !pk::is_enemy(pk::get_building(unit.target), unit))
                return true;

            if (调试模式2.v)pk::trace(pk::format("func266:{}8abnormal_task,unit.order{}, ", pk::decode(pk::get_name(unit)), unit.order));

            //如果移动到空坐标
            if (unit.order == 部队任务_移动 and unit.target_type == 部队任务对象_坐标 and pk::is_valid_pos(unit.target_pos) and !pk::get_hex(unit.target_pos).has_building and !pk::get_hex(unit.target_pos).has_unit)
                return true;

            if (调试模式2.v)pk::trace(pk::format("func266:{}9abnormal_task,unit.order{}, ", pk::decode(pk::get_name(unit)), unit.order));

            //去一个特别远的坐标,大概率是异常的
            if (unit.target_type == 部队任务对象_坐标 and pk::is_valid_pos(unit.target_pos) and pk::get_distance(unit.target_pos, unit.pos) > 50)
                return true;

            //去一个特别远的坐标,大概率是异常的
            if (unit.target_type == 部队任务对象_据点 and pk::get_building(unit.target) !is null and pk::get_distance(pk::get_building(unit.target).pos, unit.pos) > 80)
                return true;

              //打一个特别远的部队,大概率是异常的
            if (unit.target_type == 部队任务对象_部队 and pk::get_unit(unit.target) !is null and pk::get_distance(pk::get_unit(unit.target).pos, unit.pos) > 30)
                return true;


            //如果建设完成
            if (unit.order == 部队任务_修复 and (pk::get_building(unit.target) is null or (pk::get_building(unit.target) !is null and int(pk::get_building(unit.target).hp) > int(pk::get_max_hp(pk::get_building(unit.target)) * 0.9))))
                return true;

            if (调试模式2.v)pk::trace(pk::format("func266:{}10abnormal_task,unit.order{}, ", pk::decode(pk::get_name(unit)), unit.order));

            if (unit.order == 部队任务_移动 and pk::is_valid_pos(unit.target_pos) and pk::get_hex(unit.target_pos).has_building)
            {
                int spec_id = ch::to_spec_id(pk::get_building(unit.target_pos).get_id());
                if (调试模式2.v)pk::trace(pk::format("func266:{}11abnormal_task,spec_id{}, ", pk::decode(pk::get_name(unit)), spec_id));
                if (ch::is_valid_spec_id(spec_id) and pk::get_building(unit.target_pos).get_force_id() == unit.get_force_id())
                    return true;
            }
            if (调试模式2.v)pk::trace(pk::format("func266:{}12abnormal_task,unit.order{}, ", pk::decode(pk::get_name(unit)), unit.order));

            return false;

        }

        bool repair_to_ally(pk::unit @unit)
        {
            @src_unit = @unit;
            if (调试模式2.v) pk::trace(pk::format("func266:{}任务异常,尝试修改到友军, ", pk::decode(pk::get_name(unit))));

            get_list_ally_unit(unit);
            int target_count = list_ally_unit.count; // 候选目标部队数量
            if (target_count == 0)
                return false;

            list_ally_unit.sort(function(a, b) {
                float stat_a = a.troops;
                float stat_b = b.troops;
                return (stat_a > stat_b);
            });

            bool cmd = false;
            pk::unit @dst_unit = list_ally_unit[0];
            if (abnormal_task(dst_unit) and list_ally_unit.count > 1 and list_ally_unit[1] !is null)
                @dst_unit = list_ally_unit[1];
            if (abnormal_task(dst_unit) and list_ally_unit.count > 2 and list_ally_unit[2] !is null)
                @dst_unit = list_ally_unit[2];

            if (dst_unit.target_type == 部队任务对象_部队)
                cmd = pk::set_order(src_unit, dst_unit.order, pk::get_unit(dst_unit.target).pos);

            if (dst_unit.target_type == 部队任务对象_据点)
                cmd = pk::set_order(src_unit, dst_unit.order, pk::get_building(dst_unit.target).pos);

            if (dst_unit.target_type == 部队任务对象_坐标)
                cmd = pk::set_order(src_unit, dst_unit.order, dst_unit.target_pos);

            auto scenario_ai_table_unit = pk::get_scenario().ai_table.unit[unit.get_id()];
            scenario_ai_table_unit.deploy_type = pk::get_scenario().ai_table.unit[dst_unit.get_id()].deploy_type;
            scenario_ai_table_unit.deploy_target = pk::get_scenario().ai_table.unit[dst_unit.get_id()].deploy_target;

            if (cmd)
                if (调试模式2.v) pk::trace(pk::format("func266:{}任务异常,修改目标为友军部队{}的任务, ", pk::decode(pk::get_name(unit)), pk::decode(pk::get_name(dst_unit))));
            return cmd;
        }

        bool repair_to_unit(pk::unit @unit)
        {
            @src_unit = @unit;

            if (调试模式2.v) pk::trace(pk::format("func266:{}任务异常,尝试修改到敌军, ", pk::decode(pk::get_name(unit))));

            get_list_candidate_unit(unit);
            int target_count = list_candidate_unit.count; // 候选目标部队数量
            if (target_count == 0)
                return false;
            list_candidate_unit.sort(function(a, b) {
                float stat_a = pk::get_distance(main.src_unit.pos, a.pos);
                float stat_b = pk::get_distance(main.src_unit.pos, b.pos);
                return (stat_a < stat_b);
            });


            pk::unit @dst_unit = list_candidate_unit[0];

            bool cmd = pk::set_order(src_unit, 部队任务_攻击, dst_unit.pos);
            if (cmd)
                if (调试模式2.v)  pk::trace(pk::format("func266:{}任务异常,修改目标为{},坐标为{},{}, ", pk::decode(pk::get_name(unit)), pk::decode(pk::get_name(dst_unit)), dst_unit.pos.x, dst_unit.pos.y));

            return cmd;
        }



        bool repair_to_building(pk::unit @unit)
        {
            @src_unit = @unit;

            if (调试模式2.v) pk::trace(pk::format("func266:{}任务异常,尝试修改到建筑, ", pk::decode(pk::get_name(unit))));

            get_list_candidate_building(unit);
            int target_count = list_candidate_building.count; // 候选目标部队数量
            if (target_count == 0)
                return false;
            list_candidate_building.sort(function(a, b) {
                float stat_a = pk::get_distance(main.src_unit.pos, a.pos);
                float stat_b = pk::get_distance(main.src_unit.pos, b.pos);
                return (stat_a < stat_b);
            });

            pk::building @dst_base = list_candidate_building[0];

            bool cmd = pk::set_order(src_unit, 部队任务_攻击, dst_base.pos);
            if (cmd)
                if (调试模式2.v) pk::trace(pk::format("func266:{}任务异常,修改目标为{},{}的建筑, ", pk::decode(pk::get_name(unit)), dst_base.pos.x, dst_base.pos.y));
            return cmd;

        }

            // ********************************************************** 搜索可攻击敌方建筑的函数*************************************************
        void get_list_candidate_building(pk::unit @unit)
        {
            // 初始化列表
            if (!pk::is_alive(unit))
                return;
            list_candidate_building.clear();
            int weapon_id = unit.weapon;
            uint8 unit_deploy_type = 0;
            uint8 deploy_target = 255;
            auto scenario_ai_table_unit = pk::get_scenario().ai_table.unit[unit.get_id()];
            unit_deploy_type = scenario_ai_table_unit.deploy_type;// 种类(3:运输，4:建设)
            deploy_target = scenario_ai_table_unit.deploy_target;



            pk::array<pk::point> arr_t = pk::range(unit.pos, 1, 5);
            for (int j = 0; j < int(arr_t.length); j++)
            {
                pk::hex @hex = pk::get_hex(arr_t[j]);
                if (hex.has_building)
                {
                    pk::building @target_building = pk::get_building(arr_t[j]);

                    if (target_building is null)
                        continue;

                    if (!pk::is_alive(target_building))
                        continue;

                       //不是自己目标城市的建筑,尽量不去攻击
                    if (unit_deploy_type == 部队出征类型_攻击 and int(pk::get_building_id(target_building.pos)) != int(deploy_target))
                        continue;

                    if ((pk::is_enemy(unit, target_building) or (target_building.facility < 设施_阵 and target_building.get_force_id() == -1)))
                    {
                        list_candidate_building.add(target_building); // 如果敌方建筑可攻击，则添加到列表中
                    }
                }
            }
        }

        // ********************************************************** 搜索可攻击敌方部队的函数*************************************************

        void get_list_candidate_unit(pk::unit @unit)
        {
            // 初始化列表
            if (!pk::is_alive(unit))
                return;
            list_candidate_unit.clear();
            int weapon_id = unit.weapon;

            // 冲车不作为搜索目标
            if (weapon_id == 兵器_冲车)
                return;

            pk::array<pk::point> arr_t = pk::range(unit.pos, 1, 6);
            for (int j = 0; j < int(arr_t.length); j++)
            {
                pk::point pos = arr_t[j];
                pk::hex @hex = pk::get_hex(pos);

                pk::unit @target_unit = pk::get_unit(arr_t[j]);
                if (!hex.has_building and target_unit !is null and pk::is_alive(target_unit) and pk::is_enemy(unit, target_unit))
                {
                    list_candidate_unit.add(target_unit); // 如果敌方部队可攻击，则添加到列表中

                }
            }
        }

     // ********************************************************** 搜索附近我方部队 用于给异常部队复制任务*************************************************
        void get_list_ally_unit(pk::unit @unit)
        {
            // 初始化列表
            if (!pk::is_alive(unit))
                return;
            list_ally_unit.clear();
            int weapon_id = unit.weapon;


            pk::array<pk::point> arr_t = pk::range(unit.pos, 1, 6);
            for (int i = 0; i < int(arr_t.length); i++)
            {
                pk::point pos = arr_t[i];
                pk::hex @hex = pk::get_hex(pos);

                pk::unit @target_unit = pk::get_unit(arr_t[i]);
                if (!hex.has_building and target_unit !is null and pk::is_alive(target_unit) and unit.get_force_id() == target_unit.get_force_id() and unit.type == 部队类型_战斗)
                {
                    if (unit.order == 部队任务_撤退) continue;
                    if (unit.order == 部队任务_拦截 or unit.order == 部队任务_攻击 or unit.order == 部队任务_征服 or unit.order == 部队任务_攻城 or unit.order == 部队任务_移动)
                        list_ally_unit.add(target_unit); // 如果我方部队战斗中，则添加到列表中

                }
            }
        }
            // **********************************************************寻找撤退据点**********************************************************
        int loc_id;
        int service_id;
        pk::building @find_withdraw_base(pk::unit @unit)
        {
            array<pk::building @> dst_base_arr;

            main.loc_id = pk::get_building_id(unit.pos);
            if (main.loc_id < 0 or main.loc_id >= 据点_末)
                return null;
            main.service_id = pk::get_service(unit);

            for (int i = 0; i < 据点_末; i++)
            {
                pk::building @dst_base = pk::get_building(i);

                if (!pk::is_alive(dst_base))
                    continue;

                //太远不行
                if (unit_distance[loc_id][i] > 8)
                    continue;

                    //判断势力
                if (dst_base.get_force_id() != unit.get_force_id())
                    continue;

                if (unit.is_player())
                {
                    pk::district @district = pk::get_district(pk::get_building(i).get_district_id());
                    if (district.no == 1)continue;
                }

                dst_base_arr.insertLast(dst_base);
            }
            if (dst_base_arr.length == 0)return null;
            dst_base_arr.sort(function(a, b) {
                return unit_distance[main.loc_id][a.get_id()] - ((a.get_id() == main.service_id) ? 2 : 0) < unit_distance[main.loc_id][b.get_id()] - ((b.get_id() == main.service_id) ? 2 : 0);
            });

            if (dst_base_arr.length <= 0)
                return pk::get_building(pk::get_service(unit));
            else return  dst_base_arr[0];
        }

        pk::list<pk::person @> get_member_list(pk::unit@ unit)
        {
            pk::list<pk::person @> list;
            for (int i = 0; i < 3; ++i)
            {
                if (pk::is_valid_person_id(unit.member[i]))
                {
                    pk::person @person0 = pk::get_person(unit.member[i]);
                    if (pk::is_alive(person0))
                        list.add(person0);
                }
            }
            return list;
        }

        int get_tekisei(pk::list<pk::person @> list, int heishu_id)
        {
            int best_tekisei = 0;
            for (int i = 0; i < list.count; ++i)
            {
                if (list[i] !is null)
                {
                    if (list[i].tekisei[heishu_id] > best_tekisei)
                        best_tekisei = list[i].tekisei[heishu_id];
                }
                //pk::trace("兵种"+heishu_id+"最佳适性"+best_tekisei);
            }
            return best_tekisei;
        }


    //应该是确认部队出征类型对应的基础条件是否满足？
        bool check_unit_deploy_type(pk::ai_context@ ai_context, int service_force_id, int unit_deploy_type, int deploy_target)
        {

            pk::building@ building = pk::get_building(deploy_target);
            if (pk::is_alive(building))
            {
                int building_force_id = building.get_force_id();
                switch (unit_deploy_type)                        // 3为运输，4为建设
                {
                    case 部队出征类型_攻击:
                        if (pk::is_enemy(building_force_id, service_force_id))
                            return true;
                        break;
                    case 部队出征类型_防御:
                        if (building_force_id == service_force_id)
                            return ai_context.base[deploy_target].status == 据点状态_战斗;
                        break;
                    case 部队出征类型_运输:
                    case 部队出征类型_建设:
                        return service_force_id == building_force_id;
                }
            }
            return false;
        }

            //目标及目标势力是否不合适？false代表没有不合适，不需重设？true代表不合适，需要重设？
        bool check_target_suitability(pk::unit@ unit)
        {
            int district_id = unit.get_district_id();
            pk::district@ district = pk::get_district(district_id);

            if (unit.type == 部队类型_战斗)
            {
                if (unit.order != 部队任务_拦截)
                {
                    if (pk::check_setting(district, 军团设定_攻击))
                    {
                        pk::map_object@ target = pk::get_target_map_object(unit);
                        int unit_target_force_id = -1;
                        if (pk::is_alive(target))
                        {
                            unit_target_force_id = target.get_force_id();
                            if (pk::is_valid_force_id(unit_target_force_id))
                            {
                                int unit_force_id = unit.get_force_id();
                                if (unit_target_force_id == unit_force_id)//建设部队？
                                    return false;
                                if (!pk::is_enemy(unit_target_force_id, unit_force_id))
                                    return true;
                            }
                        }
                        int policy = district.policy;
                        if (policy != 军团方针_势力攻略)
                        {
                            if (policy != 军团方针_都市攻略)
                                return false;
                            pk::city@ policy_target_city = pk::get_city(district.policy_target);
                            if (pk::is_alive(policy_target_city))
                            {
                                if (!pk::is_valid_force_id(unit_target_force_id))
                                    return false;

                                if (unit_target_force_id == policy_target_city.get_force_id())
                                    return false;

                            }
                        }
                        else
                        {
                            int policy_target_force_id = district.policy_target;
                            pk::force@ target_force = pk::get_force(policy_target_force_id);
                            if (pk::is_alive(target_force))
                            {
                                if (!pk::is_valid_force_id(unit_target_force_id))
                                    return false;
                                if (unit_target_force_id == policy_target_force_id)
                                    return false;
                            }
                        }
                        return true;
                    }
                    return true;
                }
                return false;//所以战斗部队目标是拦截时，不需要检测
            }
            if (unit.type == 部队类型_运输)
            {
                pk::map_object@ target = pk::get_target_map_object(unit);
                if (pk::is_alive(target))
                {
                    if (target.get_force_id() == unit.get_force_id())
                        return false;
                }
            }
            return true;
        }

        // 获取部队的攻击最小和最大射程
        pk::int_int get_atk_range(pk::unit @unit)
        {
            pk::int_int atk_range = pk::int_int(1, 1);
            if (!pk::is_alive(unit) or unit.weapon == 兵器_剑)
                return atk_range;
            int weapon_id = unit.weapon;
            if (weapon_id < 0)
                pk::trace(pk::format("{},兵装{},", pk::decode(pk::get_name(unit), weapon_id)));

            pk::equipment @epq = pk::get_equipment(unit.weapon);
            string eqp_name = pk::decode(pk::get_name(epq));
            string info = pk::format("{}", eqp_name);
            int min_range = 5;
            int max_range = 1;
            for (int j = 0; j < 可用战法_末; j++)
            {
                if (epq.tactics[j])
                {
                    pk::tactics @tts = pk::get_tactics(j);
                    string tts_name = pk::decode(pk::get_name(tts));
                    info += pk::format(" {}({},{})", tts_name, tts.min_range, tts.max_range);
                    min_range = pk::min(min_range, tts.min_range);
                    max_range = pk::max(max_range, tts.max_range);
                }
            }
            if (weapon_id == 兵器_弩 and unit.has_tech(技巧_强弩))
                max_range += 1;
            if (weapon_id == 兵器_战马 and (unit.has_tech(技巧_骑射) or unit.has_skill(特技_白马)))
                max_range = pk::max(2, max_range);
            if ((weapon_id == 兵器_井阑 or weapon_id == 兵器_投石) and unit.has_skill(特技_射程))
                max_range += 1;
            atk_range = pk::int_int(min_range, max_range);
            return atk_range;
        }

        string get_weapon_name(int weapon_id)
        {
            string weapon_name;
            switch (weapon_id)
            {
                case 兵器_剑:
                    weapon_name = "剑兵";
                    break;
                case 兵器_枪:
                    weapon_name = "枪兵";
                    break;
                case 兵器_戟:
                    weapon_name = "戟兵";
                    break;
                case 兵器_弩:
                    weapon_name = "弓兵";
                    break;
                case 兵器_战马:
                    weapon_name = "骑兵";
                    break;
                case 兵器_冲车:
                    weapon_name = "冲车";
                    break;
                case 兵器_井阑:
                    weapon_name = "井栏";
                    break;
                case 兵器_投石:
                    weapon_name = "投石";
                    break;
                case 兵器_木兽:
                    weapon_name = "木兽";
                    break;
                case 兵器_走舸:
                    weapon_name = "走舸";
                    break;
                case 兵器_楼船:
                    weapon_name = "楼船";
                    break;
                case 兵器_斗舰:
                    weapon_name = "斗舰";
                    break;
                default:
                    weapon_name = "??";
                    break;
            }
            return weapon_name;
        }

        string get_tekisei_name(int tekisei)
        {
            string tekisei_name;
            switch (tekisei)
            {
                case 适性_C:
                    tekisei_name = "C";
                    break;
                case 适性_B:
                    tekisei_name = "B";
                    break;
                case 适性_A:
                    tekisei_name = "A";
                    break;
                case 适性_S:
                    tekisei_name = "S";
                    break;
                default:
                    tekisei_name = "↑";
                    break;
            }
            return tekisei_name;
        }
        // 获取兵种颜色函数
        string get_heishu_color(int weapon_id)
        {
            string text_color;
            float weight = main.heishu_weight[pk::equipment_id_to_heishu(weapon_id)];
            if (weapon_id == 兵器_剑)
                text_color = "\x1b[2x"; // 绿色
            else if (weight == heishu_null)
                text_color = "\x1b[29x"; // 红色
            else if (weight == heishu_weak)
                text_color = "\x1b[16x"; // 橙色
            else if (weight == heishu_normal)
                text_color = "\x1b[17x"; // 黄色
            else if (weight == heishu_strong)
                text_color = "\x1b[2x"; // 绿色
            else
                text_color = "\x1b[0x"; // 白色
            return text_color;
        }

        array<pk::point> get_empty_pos(pk::point pos, int distance_min, int distance_max)
        {
            array<pk::point> empty_pos;
            array<pk::point> range_pos_arr = pk::range(pos, distance_min, distance_max);

            for (int arr_index = 0; arr_index < int(range_pos_arr.length); arr_index++)
            {
                pk::point range_pos = range_pos_arr[arr_index];
                if (!pk::is_valid_pos(range_pos))
                    continue;

                pk::hex @hex = pk::get_hex(range_pos);
                if (hex.has_building)
                    continue;
                if (hex.has_unit)
                    continue;

                int terrain_id = hex.terrain;
                if (!pk::is_valid_terrain_id(terrain_id))
                    continue;
                if (!pk::is_enabled_terrain(terrain_id))
                    continue;

                empty_pos.insertLast(range_pos_arr[arr_index]);
            }

            return empty_pos;
        }
        string get_order_info(int order)
        {
            string name;
            switch (order)
            {
                case 0:
                    name = "待命";
                    break;
                case 1:
                    name = "移动";
                    break;
                case 2:
                    name = "设置";
                    break;
                case 3:
                    name = "征服";
                    break;
                case 4:
                    name = "撤退";
                    break;
                case 5:
                    name = "拦截";
                    break;
                case 6:
                    name = "护卫";
                    break;
                case 7:
                    name = "攻城";
                    break;
                case 8:
                    name = "修复";
                    break;
                case 9:
                    name = "征服";
                    break;
                case 10:
                    name = "补给";
                    break;
                case 11:
                    name = "歼灭";
                    break;
                case 12:
                    name = "追随";
                    break;
                case 13:
                    name = "末";
                    break;
                default:
                    name = "无";
                    break;
            }

            return name;
        }

    }

    Main main;
}
